package org.zeqp.chatAI.minio;

import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.HttpUtils;
import io.minio.messages.*;
import org.zeqp.chatAI.aiterface.animal.AnimalUtils;
import org.zeqp.chatAI.minio.eum.MimeTypeEnum;
import org.zeqp.chatAI.minio.put.BatchFilePut;
import org.zeqp.chatAI.minio.put.ObjectResultInfo;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.*;

public class MinioUtils {

    private static class MinioClientHold{
        //private static final String ACCESS_KEY="2jDJtDWhtbmPbrv0vgNA";
        private static final String ACCESS_KEY="EgTSyUysAuZ21bqe3t44";
        //private static final String SECRET_KEY="oVumwdZMgNzwISCs3zeOPumNEQmHEhvqbc3mC4Cr";
        private static final String SECRET_KEY="6AIt2yN336LOEhfJHEkycg0HPDN7uJkzoZGtRAlj";
        private static final String PUBLIC_ENDPOINT ="http://183.214.98.159";
        //private static final String PRIVATE_ENDPOINT ="http://172.17.12.21";

        private static final int CONNECTPOINTPORT=9000;

        private static final int ONLINECONNECTPOINTPORT=7000;
        private static final String PRIVATE_ENDPOINT ="http://127.0.0.1";
        private static final MinioClient client =getClient();

        public static MinioClient getClient(){
            MinioClient client  = null;
            try {
                client = MinioClient.builder().
                        endpoint(PRIVATE_ENDPOINT,CONNECTPOINTPORT,false).
                        credentials(ACCESS_KEY,SECRET_KEY).httpClient(HttpUtils.disableCertCheck(HttpUtils.newDefaultHttpClient(3000,3000,3000))).build();
            } catch (KeyManagementException e) {
                throw new RuntimeException(e);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }

            return client;
        }
    }

    /***
     * 接入
     * @return  获取一个客户端
     */
    public static MinioClient getMinioClient(){
        MinioClient client =  MinioClientHold.client;
        return client;
    }

    /***
     * 检测是否存在 bucketName
     * @param bucketName  名称
     * @param client 客户端
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public static boolean BucketExist(String bucketName,MinioClient client)  {
        System.out.println(client);
        try {
            boolean exist = client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            return exist;
        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
            System.out.println("HTTP trace: " + e.httpTrace());
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        }
        return false;
    }

    /***
     * @param bucketName 名称
     * @return true/false 成功/失败
     * 创建一个捅
     */
    public static boolean createBucket(String bucketName,MinioClient client){
        try {
            if(!MinioUtils.BucketExist(bucketName,client)){
                client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                return true;
            }
            return false;
        } catch (ErrorResponseException e) {
            throw new RuntimeException(e);
        } catch (InsufficientDataException e) {
            throw new RuntimeException(e);
        } catch (InternalException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidResponseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (ServerException e) {
            throw new RuntimeException(e);
        } catch (XmlParserException e) {
            throw new RuntimeException(e);
        }
    }

    /***
     *   删除一个空桶桶
     * @param bucketName 名称
     * @param client 客户端
     * @return true/false 成功/失败
     *
     */
    public boolean delEmptyBucket(String bucketName,MinioClient client){
        try {
            client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
            return true;
        } catch (ErrorResponseException | InsufficientDataException | InternalException| InvalidKeyException| InvalidResponseException |IOException var4 ) {
            var4.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException | ServerException |XmlParserException x) {
            x.printStackTrace();
           return false;
        }catch (MinioException minioException){
            minioException.printStackTrace();
            throw minioException;
        }

    }


    /**
     * 设置bucket加密方式
     * @param client 客户端
     * @param bucketName 目标桶
     * @param privateKey 私钥
     * @param sseTypes 加密方式
     */
    public boolean setBucketEncryption(String bucketName, SseAlgorithm sseTypes,String privateKey, MinioClient client){

        SseConfigurationRule configuration = new SseConfigurationRule(SseAlgorithm.AES256,privateKey);
        SseConfiguration config = new SseConfiguration(configuration);
        try {
            client.setBucketEncryption(SetBucketEncryptionArgs.builder().bucket(bucketName).config(config).build());
            return  true;
        } catch (ErrorResponseException | InsufficientDataException | InternalException| InvalidKeyException| InvalidResponseException |IOException var4 ) {
            var4.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException | ServerException |XmlParserException x) {
            x.printStackTrace();
            return false;
        }catch (MinioException minioException){
            minioException.printStackTrace();
            throw minioException;
        }

    }



    /***
     * 获取当前捅信息
     */


    /***
     * 获取捅信息列表
     */

    /***
     *  上传文件
     * @param client
     * @param fileName
     * @param contentType
     * @param bucket
     * @param inputStream 文件流
     *
     */
    public static String putFileObjectByIO(MinioClient client,String fileName,String  contentType,String bucket, InputStream inputStream){

        try {
            ObjectWriteResponse objectWriteResponse = client.putObject(PutObjectArgs.builder().bucket(bucket).object(fileName).contentType(contentType).stream(inputStream,inputStream.available(),-1 ).build());
            String etag = objectWriteResponse.etag();
            return etag;

        } catch (ErrorResponseException | InsufficientDataException | InternalException| InvalidKeyException| InvalidResponseException |IOException var4 ) {
            var4.printStackTrace();
        } catch (NoSuchAlgorithmException | ServerException |XmlParserException x) {
            x.printStackTrace();
        }catch (MinioException minioException){
            minioException.printStackTrace();
            throw minioException;
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

    public static StatObjectResponse getStaObject(String eTag,String bucketName,MinioClient client) {
        StatObjectResponse statObjectResponse = null;
        try {
            statObjectResponse = client.statObject(StatObjectArgs.builder().bucket(bucketName).object(eTag).build());
            return statObjectResponse;
        } catch (ErrorResponseException e) {
            JSONObject entries = JSONUtil.parseObj(e.errorResponse());
            String toJsonStr = JSONUtil.toJsonStr(e.errorResponse().toString());
            System.out.println(entries);
        } catch (InsufficientDataException e) {
            throw new RuntimeException(e);
        } catch (InternalException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidResponseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (ServerException e) {
            throw new RuntimeException(e);
        } catch (XmlParserException e) {
            throw new RuntimeException(e);
        }
        return  null;
    }

    /***
     * 为object 打上tag 标签
     * @param header  标签key value
     * @param objName 对象名称
     * @param bucketName bucketName
     * @param client 客户端
     * @return
     */
    public static boolean setObjectTAGS(Map<String,String> header,String objName,String bucketName,MinioClient client){
        try {
            client.setObjectTags(SetObjectTagsArgs.builder().bucket(bucketName).object(objName).tags(header).build());
            return true;
        } catch (ErrorResponseException e) {
            try {
                throw new MinioException(e.getMessage());
            } catch (MinioException ex) {
                throw new RuntimeException(ex);
            }
        } catch (InsufficientDataException e) {
            throw new RuntimeException(e);

        } catch (InternalException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidResponseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (ServerException e) {
            throw new RuntimeException(e);
        } catch (XmlParserException e) {
            throw new RuntimeException(e);
        }
    }


    /***
     * 创建一个文件夹
     * @param bucketName 所属bucketName
     * @param folderName 文件夹名称
     * @param client
     */
    public static ObjectWriteResponse createFolder(String bucketName,String folderName,MinioClient client){
        try {
            ObjectWriteResponse response = client.putObject(PutObjectArgs.builder().bucket(bucketName).object("/"+folderName+"/").stream(
                            new ByteArrayInputStream(new byte[]{}), 0, -1)
                    .build());
            return response;
        } catch (ErrorResponseException | InsufficientDataException | InternalException| InvalidKeyException| InvalidResponseException |IOException var4 ) {
            var4.printStackTrace();
        } catch (NoSuchAlgorithmException | ServerException |XmlParserException x) {
            x.printStackTrace();
        }catch (MinioException minioException){
            minioException.printStackTrace();
            throw minioException;
        }
        return null;
    }


    /***
     * 单次会话 - 批量添加对象
     * @param listObjects 对象信息
     * @param client 客户端
     * @param bucketName 所属bucket
     * @return  会话id
     */
    public static ObjectWriteResponse putObjects(List<BatchFilePut> listObjects , MinioClient client, String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        ZonedDateTime time = ZonedDateTime.now();
        List<SnowballObject> snowballObjectList = new ArrayList<>();
        for(int i = 0 ; i <listObjects.size();i++){
            BatchFilePut batchFilePut = listObjects.get(i);
            InputStream curStream = batchFilePut.getFileInputStream();
            byte[] bytes = IoUtil.readBytes(curStream, false);
            long length  = bytes.length;
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            SnowballObject snowballObject = new SnowballObject(batchFilePut.getFileName(),byteArrayInputStream,length,time);
            snowballObjectList.add(snowballObject);
            byteArrayInputStream.close();
        }
        //snowball.6567110666440901783.tar

        ObjectWriteResponse response = client.uploadSnowballObjects(UploadSnowballObjectsArgs.builder().bucket(bucketName).objects(snowballObjectList).build());
//        listObjects.stream().forEach(p->p.destroyStream(p.getFileInputStream()));
        for( int i = 0 ; i<listObjects.size();i++){
            BatchFilePut batchFilePut = listObjects.get(i);
            batchFilePut.getFileInputStream().close();
        }
        return response;
    }


    public static void getListObjects(String bucketName,MinioClient client){
        List<ObjectResultInfo> resultInfoList = new ArrayList<>();
        Iterable<Result<Item>> results = client.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());

        Iterator<Result<Item>> iterator = results.iterator();
        while (iterator.hasNext()){
            Result<Item> next = iterator.next();
            try {
                Item item = next.get();
                String etag = item.etag();
                boolean deleteMarker = item.isDeleteMarker();
                String objectName = item.objectName();
                long size = item.size();
                boolean latest = item.isLatest();
                Owner owner = item.owner();
                String displayName = owner!=null? owner.displayName() : null;
                String ownerId = owner!=null?owner.id():null;
                ZonedDateTime time = null;
                if(!item.isDir()) {
                     time = (null == item.lastModified() ? null : item.lastModified());
                }else {
                     time = null;
                }
                String storageClass = null==item.storageClass()?null:item.storageClass();
                String versionId = item.versionId();
                ObjectResultInfo resultInfo = new ObjectResultInfo(etag,deleteMarker,objectName,size,latest,displayName,ownerId,time, storageClass,versionId);
                resultInfoList.add(resultInfo);
            } catch (ErrorResponseException e) {
                throw new RuntimeException(e);
            } catch (InsufficientDataException e) {
                throw new RuntimeException(e);
            } catch (InternalException e) {
                throw new RuntimeException(e);
            } catch (InvalidKeyException e) {
                throw new RuntimeException(e);
            } catch (InvalidResponseException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            } catch (ServerException e) {
                throw new RuntimeException(e);
            } catch (XmlParserException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println(JSONUtil.toJsonStr(resultInfoList));

    }


    public static String getFileMimeType(String extFileName){
        return MimeTypeEnum.getContentType(extFileName);
    }

    /***
     * 删除文件
     */

    /***
     * 修改文件信息
     */
    public static void main(String[] args) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        ClassLoader classLoader = AnimalUtils.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("1.png");
        InputStream resourceAsStream2 = classLoader.getResourceAsStream("2.jpg");
        //通塞端口 通过IO流上传文件
         // String eTag = MinioUtils.putFileObjectByIO(MinioUtils.getMinioClient(),"6.png", MinioUtils.getFileMimeType("png"),"test",resourceAsStream);
          //System.out.println("etag ========{}"+eTag);
        //48fbb4b2ada710f51cdd73bb7a140189
//        MinioUtils.getStaObject("5.png","test",MinioUtils.getMinioClient());
        //48fbb4b2ada710f51cdd73bb7a140189
        //String type = MimeTypeEnum.getContentType("png");
        //System.out.println(type);
        //MinioUtils.createFolder("sss1","nihao",MinioUtils.getMinioClient());
//        Map<String,String> tags  = new HashMap<>();
//        tags.put("Name","a picture");
//        tags.put("description","a boy about six years old");
//        tags.put("allow","read:write");
//        boolean sss1 = MinioUtils.setObjectTAGS(tags, "5.png", "sss1", MinioUtils.getMinioClient());
//        System.out.println(sss1);

        List<BatchFilePut> filePuts = new ArrayList<>();
        BatchFilePut bee = new BatchFilePut();
        bee.setFileInputStream(resourceAsStream);
        bee.setFileName("动物1.png");

        BatchFilePut bee2 = new BatchFilePut();
        bee2.setFileInputStream(resourceAsStream2);
        bee2.setFileName("植物1.jpg");
          filePuts.add(bee);
        filePuts.add(bee2);
        ObjectWriteResponse response = MinioUtils.putObjects(filePuts, MinioUtils.getMinioClient(), "test");
        System.out.println(response.toString());

    //    MinioUtils.getListObjects("test",MinioUtils.getMinioClient());
    }





}
